home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / scsh-0.4 / scsh-0 / scsh-0.4.2 / scsh / dirstuff1.c < prev    next >
C/C++ Source or Header  |  1995-10-22  |  4KB  |  142 lines

  1. /* Here is stuff for interfacing to directories.
  2. ** Copyright (c) 1993, 1994 by Olin Shivers.
  3. */
  4.  
  5. #include <sys/types.h>
  6. #include <stdio.h>
  7. #include <dirent.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #include "libcig.h"
  12. #include "scsh_aux.h"
  13.  
  14. /* Make sure our exports match up w/the implementation: */
  15. #include "dirstuff1.h"
  16.  
  17. extern int errno;
  18.  
  19. /* Linked list of malloc'd entries. */
  20. struct scm_dirent_struct
  21.     { char *fname;            /* File name */ 
  22.       struct scm_dirent_struct *next;};    /* Next pointer */
  23. typedef struct scm_dirent_struct scm_dirent_t;
  24.  
  25. void free_dirent_list(scm_dirent_t *entry)
  26. {
  27.      while(entry) {
  28.      scm_dirent_t *next = entry->next;
  29.      Free(entry);
  30.      entry = next;
  31.      }
  32.      }
  33.  
  34. /* Returns [err, fnames, len]
  35. ** err is 0 for success, otw errno.
  36. ** fnames is a vector of strings (filenames), null terminated.
  37. ** len is the length of fnames.
  38. */
  39. int open_dir(const char *dirname,  char ***fnames, int *len)
  40. {
  41.     scm_dirent_t *dep, *entries;
  42.     struct dirent *dirent;
  43.     char *fname, **dirvec, **vecp;
  44.     DIR *d;
  45.     int num_entries;
  46.     int e; /* errno temp */
  47.  
  48.     if( NULL == (d = opendir(dirname)) ) return errno;
  49.     
  50.     entries = NULL; num_entries = 0;
  51.     while( NULL != (dirent = readdir(d)) ) {
  52.     if((strcmp(dirent->d_name,".") == 0) || (strcmp(dirent->d_name,"..") == 0))
  53.         continue;
  54.     if( NULL == (dep=Alloc(scm_dirent_t)) )
  55.         {e=errno; goto lose2;}
  56.     if( NULL == (fname=copystring(NULL, dirent->d_name)) ) goto lose1;
  57.     dep->fname = fname;
  58.     dep->next = entries;
  59.     entries = dep; num_entries++;
  60.     }
  61.     closedir(d);
  62.     
  63.     /* Load the filenames into a vector and free the structs. */
  64.     if( NULL == (dirvec = Malloc(char *, num_entries+1)) )
  65.     {e=errno; goto lose3;}
  66.     for(dep=entries, vecp=dirvec;  dep;  vecp++) {
  67.     scm_dirent_t *next = dep->next;
  68.     *vecp = dep->fname;
  69.     Free(dep);
  70.     dep = next;
  71.     }
  72.     dirvec[num_entries] = NULL;
  73.     
  74.     *fnames = dirvec;
  75.     *len = num_entries;
  76.     return 0;
  77.  
  78.  
  79.   lose1: e = errno; Free(dep);
  80.   lose2: closedir(d);
  81.   lose3: free_dirent_list(entries);
  82.     return e;
  83.     }
  84.  
  85.  
  86. #define DOTFILE(a) ((a) && *(a) == '.') /* Not a function. */
  87.  
  88. /* a <= b in the Unix filename ordering:
  89. **   dotfiles come first, lexicographically ordered.
  90. **   others come second, lexicographically ordered.
  91. **
  92. ** This is for sorting filenames in directory listings.
  93. */
  94.  
  95. static int compare_fname(const void *aptr, const void *bptr)
  96. {
  97.     char const *a = * (char const * *) aptr;
  98.     char const *b = * (char const * *) bptr;
  99.     if( DOTFILE(a) )
  100.     return DOTFILE(b) ? strcmp(a+1,b+1) : -1;
  101.     return DOTFILE(b) ? 1 : strcmp(a,b);
  102. }
  103.  
  104.  
  105. void scm_sort_filevec(const char **dirvec, int nelts)
  106. {
  107.     qsort((char *) dirvec, nelts, sizeof(char*), compare_fname);
  108.     }
  109.  
  110. #if 0
  111. /* This one is a little more complex, but we don't use it because we
  112. ** never try to sort lists of filenames with . or .. in the list.
  113. */
  114.  
  115. /* Boolean function: a <= b in the Unix filename ordering:
  116. **   . comes first
  117. **   .. comes second
  118. **   Other dotfiles come next, lexicographically ordered.
  119. **   Non-dotfiles come last, lexicographically ordered.
  120. **
  121. ** This is for sorting filenames in directory listings.
  122. */
  123.  
  124. static int comp1(const void *aptr, const void* bptr)
  125. {
  126.     char const *a = *(char const **)aptr;
  127.     char const *b = *(char const **)bptr;
  128.  
  129.     if(streq(a,b)) return 0;
  130.  
  131.     if(DOTFILE(a))
  132.     if( DOTFILE(b) )
  133.         return streq(a, ".") || 
  134.                    (!streq(b, ".") && (streq(a, "..") || (!streq(b, "..") &&
  135.                               (strcmp(a,b) <= 0))))
  136.                ? -1 : 1;
  137.     else return -1;
  138.  
  139.     else return DOTFILE(b) ? 1 : strcmp(a,b);
  140. }
  141. #endif
  142.